package com.zjdiepu.www.manage.api.dz;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jxls.exception.ParsePropertyException;
import net.sf.jxls.reader.ReaderBuilder;
import net.sf.jxls.reader.XLSReadStatus;
import net.sf.jxls.reader.XLSReader;
import net.sf.jxls.transformer.XLSTransformer;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.SAXException;

import com.zjdiepu.www.base.BaseController;
import com.zjdiepu.www.base.annotation.Add;
import com.zjdiepu.www.base.annotation.Update;
import com.zjdiepu.www.base.core.AbstractSysUser;
import com.zjdiepu.www.base.core.ApiResponse;
import com.zjdiepu.www.base.core.PageVo;
import com.zjdiepu.www.base.enums.status.DpStatus;
import com.zjdiepu.www.base.enums.type.OperateType;
import com.zjdiepu.www.base.enums.type.ResultFlagType;
import com.zjdiepu.www.common.util.CollectionInitUtil;
import com.zjdiepu.www.common.util.DateUtil;
import com.zjdiepu.www.common.util.RegexUtil;
import com.zjdiepu.www.common.util.UUIDFactory;
import com.zjdiepu.www.commpent.RedisObjectClient;
import com.zjdiepu.www.convert.MyDateConverter;
import com.zjdiepu.www.convert.MyDoubleConverter;
import com.zjdiepu.www.ibiz.dz.IDzLendingImportListService;
import com.zjdiepu.www.ibiz.yw.IYwBusinessService;
import com.zjdiepu.www.ibiz.yw.IYwFeesService;
import com.zjdiepu.www.model.dz.dto.DzLendingImportList;
import com.zjdiepu.www.model.dz.ext.DzLendingImportListExt;
import com.zjdiepu.www.model.yw.dto.YwBusiness;
import com.zjdiepu.www.util.ExceptionHelper;

/**
 * 银行放款批量导入信息Controller层<br/>
 * @author xiongxiaotun<br/>
 * @time 2017年08月30日 14时09分<br/>
 * @since 1.0<br/>
 */
@RestController
@RequestMapping(value= "DzLendingImportListController", produces="application/json;charset=UTF-8")
@Api(tags = {"银行放款批量导入信息"}, produces="application/json;charset=UTF-8")
public class DzLendingImportListController extends BaseController {
	private static Logger logger = LoggerFactory.getLogger(DzLendingImportListController.class);
    @Resource
    private IDzLendingImportListService dzLendingImportListService;
    @Resource
    private IYwBusinessService ywBusinessService;
    @Resource
    private IYwFeesService ywFeesService;
    @Resource
    private RedisObjectClient redisObjectClient;
    
   /**
    * 银行放款excel导入
    * @author xiongxiaotun <br/>
    * @Title: upload  <br/>
    * @Description: 银行放款excel导入  <br/>
    * @param file
    * @param preview
    * @return
    * @version V1.0  <br/>
    */
	@RequestMapping(value = "upload", method = {RequestMethod.POST} )
	public ApiResponse upload(@RequestParam("uploadfile") MultipartFile file, HttpServletRequest request) {
		AbstractSysUser currentUser = getCurrentUser();
		if(null == file) {
			ExceptionHelper.thow("9999", "导入文件不能为空");
		}
		InputStream dzLendingImportConfig = null;
		InputStream dzLendingImportDatas = null;
		try {
			dzLendingImportConfig = request.getSession(true).getServletContext().getResourceAsStream("/WEB-INF/templet/dzLendingImportConfig.xml");
			if(null == dzLendingImportConfig) {
				ExceptionHelper.thow("9999", "读取模板文件失败！");
			}
			Map<String,List<DzLendingImportList>> dataHolders = new HashMap<>();
			List<DzLendingImportList> dzLendingImportList = new ArrayList<>();
			dataHolders.put("dzLendingImportList", dzLendingImportList);
	        dzLendingImportDatas = file.getInputStream();
	        
	        String uuid = UUIDFactory.getUUID(); //放款批次号
	        XLSReader mainReader = ReaderBuilder.buildFromXML(dzLendingImportConfig);
			//必须在buildFromXML之后
			ConvertUtils.register(new MyDateConverter(), Date.class);
		    ConvertUtils.register(new MyDoubleConverter(), Double.class);
			XLSReadStatus readStatus = mainReader.read(dzLendingImportDatas, dataHolders);
			if(readStatus.isStatusOK()) {
				if(CollectionUtils.isNotEmpty(dzLendingImportList)) {
					String errorReasonErrorNo = "该客户身份证格式不对";
					String errorReasonEmptyNo = "该客户身份证为空";
					String errorReasonEmpty = "该客户系统中没有订单";
					String errorReasonRepeat = "该客户有多笔订单";
					String errorReasonAmountLoaningEmptyOrError = "放款金额为空或格式不对";
					String errorReasonTimeLendingEmptyOrError = "放款时间为空或格式不对";
					DecimalFormat decimalFormat = new DecimalFormat("########0.00");
					//保存十分钟
					List<DzLendingImportList> goodDzLendingImportList = CollectionInitUtil.emptyList();
					List<DzLendingImportList> badDzLendingImportList = CollectionInitUtil.emptyList();
//					List<String> customerNos = dzLendingImportList.stream().map(item -> (item.getCustomerNo() == null ? null : item.getCustomerNo().trim()))
//							.filter(item -> StringUtils.isNotBlank(item)).collect(Collectors.toList());
					for(DzLendingImportList dzLendingImport: dzLendingImportList) {
						dzLendingImport.initInsertData(currentUser.getId(), currentUser.getName());
						
						String customerNo = dzLendingImport.getCustomerNo();
						if(StringUtils.isBlank(customerNo)) {
							dzLendingImport.setErrorReason(errorReasonEmptyNo);
							badDzLendingImportList.add(dzLendingImport);
							continue;
						}
						
						customerNo = customerNo.toUpperCase().trim();
						if(!RegexUtil.isCard(customerNo)) {
							dzLendingImport.setErrorReason(errorReasonErrorNo);
							badDzLendingImportList.add(dzLendingImport);
							continue;
						}
						dzLendingImport.setCustomerNo(customerNo);
						
						
						Double amountLoaning = dzLendingImport.getAmountLoaning();
						if(null == amountLoaning || 0.0D == amountLoaning) {
							dzLendingImport.setErrorReason(errorReasonAmountLoaningEmptyOrError);
							badDzLendingImportList.add(dzLendingImport);
							continue;
						}
						dzLendingImport.setAmountLoaningString(decimalFormat.format(amountLoaning));
						
						Double feeService = dzLendingImport.getFeeService();
						dzLendingImport.setFeeServiceString(feeService == null ? "0.00" : decimalFormat.format(feeService));
						
						Date timeLending = dzLendingImport.getTimeLending();
						if(null == timeLending) {
							dzLendingImport.setErrorReason(errorReasonTimeLendingEmptyOrError);
							badDzLendingImportList.add(dzLendingImport);
							continue;
						}
						dzLendingImport.setTimeLendingString(DateUtil.dateTo8String3(timeLending));
						
						YwBusiness ywBusiness = new YwBusiness();
						ywBusiness.setCustomerNo(customerNo);
						ywBusiness.setDpStatus(DpStatus.NORMAL.getCode());
						int countCustomerNo = ywBusinessService.countRefined(ywBusiness);
						if(countCustomerNo == 0) {
							dzLendingImport.setErrorReason(errorReasonEmpty);
							badDzLendingImportList.add(dzLendingImport);
						} else if(countCustomerNo > 1) {
							dzLendingImport.setErrorReason(errorReasonRepeat);
							badDzLendingImportList.add(dzLendingImport);
						} else {
							ywBusiness = ywBusinessService.selectRefined(ywBusiness);
							String busiId = ywBusiness.getId();
							dzLendingImport.setBusiId(busiId);
							dzLendingImport.setCusId(ywBusiness.getCustomerId());
							dzLendingImport.setLendingBatchId(uuid);
							dzLendingImport.setAmountLending((dzLendingImport.getFeeService() == null ? 0.0 : dzLendingImport.getFeeService()) 
									+ (dzLendingImport.getAmountLoaning() == null ? 0.0 : dzLendingImport.getAmountLoaning()));
							goodDzLendingImportList.add(dzLendingImport);
						}
					}
					long exprie = 600;
					if(CollectionUtils.isNotEmpty(goodDzLendingImportList)) {
						redisObjectClient.putExpire(uuid, goodDzLendingImportList, exprie, "good");
					}
					if(CollectionUtils.isNotEmpty(badDzLendingImportList)) {
						redisObjectClient.putExpire(uuid, badDzLendingImportList, exprie, "bad");
					}
				}
				return ApiResponse.success(uuid); 
			} else {
				return ApiResponse.fail("9999","读取导入文件数据失败");
			}
		} catch (IOException | SAXException | InvalidFormatException e) {
			logger.error("银行放款excel导入,异常栈:{}", e);
			return ApiResponse.fail("9999","导入文件发生异常");
		} finally {
				try {
					if(null != dzLendingImportDatas){
						dzLendingImportDatas.close();
					}
					if(null != dzLendingImportConfig) {
						dzLendingImportConfig.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
	}
	
	/**
	 * 导出错误数据
	 * @author xiongxiaotun <br/>
	 * @Title: exportBads  <br/>
	 * @Description: 导出错误数据 <br/>
	 * @param uuidKey   //放款批次号
	 * @return
	 * @version V1.0  <br/>
	 */
	@RequestMapping(value = "exportBads", method = {RequestMethod.GET, RequestMethod.POST} )
	public ApiResponse exportBads(HttpServletResponse response, String uuidKey, @RequestParam(defaultValue="0")boolean check) {
		getCurrentUser();
		if(StringUtils.isBlank(uuidKey)) {
			ExceptionHelper.thow(ResultFlagType.PARAM_EMPTY);
		}
		List<DzLendingImportList> badDzLendingImportList = redisObjectClient.get(uuidKey, "bad");
		if(CollectionUtils.isEmpty(badDzLendingImportList)) {
			return ApiResponse.fail("9999", "没有错误导入数据");
		}
		if(check) {
			return ApiResponse.success(true);
		}
		String templet = request.getSession(true).getServletContext().getRealPath("/WEB-INF/templet/yin_hang_fang_kuan_cuo_wu_mu_ban_@_cai_wu.xls");
		try (FileInputStream is = new FileInputStream(templet); ){
			XLSTransformer transformer = new XLSTransformer();  
			//展示数据
	    	Map<String, Object> responseData = CollectionInitUtil.emptyMap();
	    	responseData.put("dzLendingImportList", badDzLendingImportList);
			Workbook workbook = transformer.transformXLS(is, responseData);
			String fileName = "银行放款名单导入错误数据@财务";
			response.reset();
			response.addHeader("Content-Disposition",
					"attachment;filename=" + new String(fileName.getBytes(isIE(request)?"GBK":"UTF-8"), "ISO-8859-1") +".xls");
			response.setContentType("application/vnd.ms-excel;charset=UTF-8");
			OutputStream outPutStream = response.getOutputStream();
			workbook.write(outPutStream);  
		} catch (ParsePropertyException | InvalidFormatException | IOException e) {
			logger.error("导出银行放款名单导入错误数据.异常栈:{}", e);
		}
		return null;
	}
	
	/**
	 * 预览正确数据
	 * @author xiongxiaotun <br/>
	 * @Title: previewGoods  <br/>
	 * @Description: 预览 <br/>
	 * @param uuidKey
	 * @return
	 * @version V1.0  <br/>
	 */
	@RequestMapping(value = "previewGoods", method = {RequestMethod.POST} )
	public ApiResponse previewGoods(String uuidKey) {
		getCurrentUser();
		if(StringUtils.isBlank(uuidKey)) {
			ExceptionHelper.thow(ResultFlagType.PARAM_EMPTY);
		}
		List<DzLendingImportList> goodDzLendingImportList = redisObjectClient.get(uuidKey, "good");
		if(CollectionUtils.isEmpty(goodDzLendingImportList)) {
			goodDzLendingImportList = CollectionInitUtil.emptyList();
		}
		return ApiResponse.success(goodDzLendingImportList);
	}
	/**
	 * 预览错误数据
	 * @author xiongxiaotun <br/>
	 * @Title: previewBads  <br/>
	 * @Description: 预览 <br/>
	 * @param uuidKey
	 * @return
	 * @version V1.0  <br/>
	 */
	@RequestMapping(value = "previewBads", method = {RequestMethod.POST} )
	public ApiResponse previewBads(String uuidKey) {
		getCurrentUser();
		if(StringUtils.isBlank(uuidKey)) {
			ExceptionHelper.thow(ResultFlagType.PARAM_EMPTY);
		}
		List<DzLendingImportList> goodDzLendingImportList = redisObjectClient.get(uuidKey, "bad");
		if(CollectionUtils.isEmpty(goodDzLendingImportList)) {
			goodDzLendingImportList = CollectionInitUtil.emptyList();
		}
		return ApiResponse.success(goodDzLendingImportList);
	}
	
	/**
	 * 导入
	 * @author xiongxiaotun <br/>
	 * @Title: importGoods  <br/>
	 * @Description: 预览 <br/>
	 * @param uuidKey
	 * @return
	 * @version V1.0  <br/>
	 */
	@RequestMapping(value = "importGoods", method = {RequestMethod.POST} )
	public ApiResponse importGoods(String uuidKey, String bankCode, String bankName) {
		AbstractSysUser currentUser = getCurrentUser();
		if(StringUtils.isBlank(uuidKey) || StringUtils.isBlank(bankCode) || StringUtils.isBlank(bankName)) {
			ExceptionHelper.thow(ResultFlagType.PARAM_EMPTY);
		}
		List<DzLendingImportList> goodDzLendingImportList = redisObjectClient.get(uuidKey, "good");
		if(CollectionUtils.isEmpty(goodDzLendingImportList)) {
			return ApiResponse.fail("9999", "没有数据可以导入,请导出错误数据核查");
		}
		dzLendingImportListService.saveImportGoods(goodDzLendingImportList, uuidKey, bankCode, bankName, currentUser);
		return ApiResponse.success(true);
	}

    /**
     * @author xiongxiaotun <br/>
     * @Title: save  <br/>
     * @Description: 新增银行放款批量导入信息 <br/>
     * @param dzLendingImportList
     * @return
     * @version V1.0  <br/>
     */
    @ApiOperation(value = "新增银行放款批量导入信息", response = Boolean.class, httpMethod="POST", tags={"新增"})
    @RequestMapping(value = "save", method = RequestMethod.POST)
    public ApiResponse save(@Validated(Add.class) @ModelAttribute DzLendingImportList dzLendingImportList) {
    	AbstractSysUser currentUser = getCurrentUser();
    	dzLendingImportList.setModifier(currentUser.getId()); //统一使用修改人和修改人名称来初始化
    	dzLendingImportList.setModifierName(currentUser.getName());
        dzLendingImportListService.saveUpdateAndDelete(dzLendingImportList, OperateType.add);
        return ApiResponse.success(true);
    }

    /**
     * @author xiongxiaotun <br/>
     * @Title: remove  <br/>
     * @Description: 删除银行放款批量导入信息<br/>
     * @param id
     * @return
     * @version V1.0  <br/>
     */
    @ApiOperation(value = "删除银行放款批量导入信息", response = Boolean.class, httpMethod="POST", tags={"删除"})
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "数据主键", paramType="query", required = true, example="1")
    })
    @RequestMapping(value = "remove", method = RequestMethod.POST)
    public ApiResponse remove(String id) {
    	if(StringUtils.isBlank(id)) {
    		return ApiResponse.fail(ResultFlagType.PARAM_EMPTY);
    	}
    	AbstractSysUser currentUser = getCurrentUser();
    	List<String> ids = Arrays.asList(id.split(","));
    	dzLendingImportListService.updateBatch(currentUser.getId(), currentUser.getName(), DpStatus.DELETED.getCode(), ids);
        return ApiResponse.success(true);
    }
    
    /**
     * @author xiongxiaotun <br/>
     * @Title: disable  <br/>
     * @Description: 禁用银行放款批量导入信息<br/>
     * @param id
     * @return
     * @version V1.0  <br/>
     */
    @ApiOperation(value = "禁用银行放款批量导入信息", response = Boolean.class, httpMethod="POST", tags={"禁用"})
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "数据主键", paramType="query", required = true, example="1")
    })
    @RequestMapping(value = "disable", method = RequestMethod.POST)
    public ApiResponse disable(String id) {
    	if(StringUtils.isBlank(id)) {
    		return ApiResponse.fail(ResultFlagType.PARAM_EMPTY);
    	}
    	AbstractSysUser currentUser = getCurrentUser();
    	List<String> ids = Arrays.asList(id.split(","));
    	dzLendingImportListService.updateBatch(currentUser.getId(), currentUser.getName(), DpStatus.INVALID.getCode(), ids);
        return ApiResponse.success(true);
    }
    
    /**
     * @author xiongxiaotun <br/>
     * @Title: enable <br/>
     * @Description: 启用银行放款批量导入信息<br/>
     * @param id
     * @return
     * @version V1.0  <br/>
     */
    @ApiOperation(value = "启用银行放款批量导入信息", response = Boolean.class, httpMethod="POST", tags={"启用"})
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "数据主键", paramType="query", required = true, example="1")
    })
    @RequestMapping(value = "enable", method = RequestMethod.POST)
    public ApiResponse enable(String id) {
    	if(StringUtils.isBlank(id)) {
    		return ApiResponse.fail(ResultFlagType.PARAM_EMPTY);
    	}
    	AbstractSysUser currentUser = getCurrentUser();
    	List<String> ids = Arrays.asList(id.split(","));
    	dzLendingImportListService.updateBatch(currentUser.getId(), currentUser.getName(), DpStatus.NORMAL.getCode(), ids);
        return ApiResponse.success(true);
    }

    /**
     * @author xiongxiaotun <br/>
     * @Title: modify  <br/>
     * @Description: 修改银行放款批量导入信息 <br/>
     * @param dzLendingImportList
     * @return
     * @version V1.0  <br/>
     */
    @ApiOperation(value = "修改银行放款批量导入信息", response = Boolean.class, httpMethod="POST", tags={"修改"})
    @RequestMapping(value = "modify", method = RequestMethod.POST)
    public ApiResponse modify(@Validated(Update.class) @ModelAttribute DzLendingImportList dzLendingImportList) {
    	AbstractSysUser currentUser = getCurrentUser();
    	dzLendingImportList.setModifier(currentUser.getId()); //统一使用修改人和修改人名称来初始化
    	dzLendingImportList.setModifierName(currentUser.getName());
    	dzLendingImportListService.saveUpdateAndDelete(dzLendingImportList, OperateType.edit);
        return ApiResponse.success(true);
    }

    /**
     * @author xiongxiaotun <br/>
     * @Title: getById  <br/>
     * @Description: 主键查询银行放款批量导入信息<br/>
     * @param id
     * @return
     * @version V1.0  <br/>
     */
    @ApiOperation(value = "主键查询银行放款批量导入信息", response = DzLendingImportList.class, httpMethod="POST", tags={"主键查询"})
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "数据主键", paramType="query", required = true, example="1")
    })
    @RequestMapping(value = "getById", method = RequestMethod.POST)
    public ApiResponse getById(String id){
    	if(StringUtils.isBlank(id)) {
    		return ApiResponse.fail(ResultFlagType.PARAM_EMPTY);
    	}
       DzLendingImportList dzLendingImportList = dzLendingImportListService.selectById(id);
       if(null == dzLendingImportList) {
    	   return ApiResponse.fail(ResultFlagType.MISSING);
       }
       return ApiResponse.success(dzLendingImportList);
    }
    
    /**
     * @author xiongxiaotun <br/>
     * @Title: list  <br/>
     * @Description: 条件查询银行放款批量导入信息 <br/>
     * @param dzLendingImportListExt
     * @return
     * @version V1.0  <br/>
     */
    @ApiOperation(value = "条件查询银行放款批量导入信息",response = DzLendingImportList.class, httpMethod="POST", tags={"列表"})
    @RequestMapping(value = "list", method = RequestMethod.POST)
    public ApiResponse list(@ModelAttribute DzLendingImportListExt dzLendingImportListExt, @RequestParam(defaultValue="true") boolean preview){
        dzLendingImportListExt.notDeleted();
        PageVo page = getPage(dzLendingImportListExt);
        int records = dzLendingImportListService.countByExt(dzLendingImportListExt);
        page.setRecords(records);
        if (records > 0) {
            List<DzLendingImportList> dzLendingImportLists = dzLendingImportListService.selectByExt(dzLendingImportListExt);
            page.setRows(dzLendingImportLists);
        } else {
            page.setRows(CollectionInitUtil.emptyList());
        }
        return ApiResponse.success(page);
    }

}
